<?php

namespace app\api\controller;

use think\Cache;
use think\Controller;
use app\api\model\Order as OrderModel;
use app\api\model\Orders;
use app\api\model\Device;
use app\api\model\YearcardLog;
use app\api\model\YearcardUser;
use app\api\model\CouponMember;
use think\Request;
use think\Db;

/**
 * Class Order
 * @package app\reserve\controller
 * @author zhenHong~
 * 用户保养订单
 */
class Order extends Controller
{

    protected $model = '';

    public function __construct(Request $request = null)
    {
        parent::__construct($request);
        $this->model = new OrderModel();
        $this->orders = new Orders();
        Vendor('WxPay.lib.WxPay#Api');
        Vendor('WxPay.WxPay#JsApiPay');
    }

    /**
     * @param Request $request
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author zhenHong~
     * 用户下单
     */
    public function createMyOrder(Request $request)
    {
        $data = $request->post();
        $check = $this->validate($data, 'Order.createMyOrder');
        if ($check !== true) {
            return apiResponse(201, $check, '');
        }
        $devicemodel = new Device();
        $device = $devicemodel -> deviceInfo("id=".$data['d_id']);
        if (empty($device)) {
            return apiResponse("201","设备不存在！");
        }
        if ( $device['device_status'] != 1 ) {
            return apiResponse("201","设备已开启或已故障，暂时无法服务！");
        }
        $data['pay_price'] = $device['price'];
        $data['status'] = 1;
        Db::startTrans();
        try{
            if ( in_array($data['pay_type'],[2,3])) {

                if (empty($data['y_id'])) {
                    return apiResponse("201","未指定年卡！");
                }
                $yearuser = new YearcardUser();
                $where['id'] = $data['y_id'];
                $where['begin_time'] = array('ELT', time());
                $where['end_time'] = array('EGT', time());
                $where['u_id'] = $data['u_id'];
                $where['status'] = 1; //已支付的年卡和次卡
                $where['type'] = $data['pay_type'] == 2 ? 1 : 2;//支付类型为2年卡查询type为1的储蓄卡
                $myyearcard = $yearuser -> yearCardInfo($where);
                if (!empty($myyearcard)) {
                    if ($myyearcard['type'] == 1) {
                        //储蓄卡
                        if ($myyearcard['balance'] < $data['pay_price']) {
                            return apiResponse("201","年卡余额不足！");
                        }
                        $y_user = array(
                                'id' => $myyearcard['id'],
                                'balance' => $myyearcard['balance'] - $data['pay_price'],
                            );
                        $y_log_obj = array(
                                'pay_time' => time(),
                                'y_u_id' => $myyearcard['id'],
                                'balance' => $myyearcard['balance'] - $data['pay_price'],
                                'type' => 1,
                                'price' => $data['pay_price'],
                                'd_id' => $data['d_id']
                            );
                    }else{
                        //2次卡
                        if ($myyearcard['balance_num'] < 1 ) {
                            return apiResponse("201","该次卡已使用完！");
                        }
                        $data['pay_price'] = 0;
                        $y_user = array(
                                'id' => $myyearcard['id'],
                                'balance_num' => $myyearcard['balance_num'] - 1
                            );
                        $y_log_obj = array(
                                'pay_time' => time(),
                                'y_u_id' => $myyearcard['id'],
                                'balance_num' => $myyearcard['balance_num'] - 1,
                                'type' => 2,
                                'price' => $data['pay_price'],
                                'd_id' => $data['d_id']
                            );
                    }
                    $y_log = new YearcardLog();
                    $yearuser ->isUpdate()-> save($y_user);
                    $y_log -> allowField(true)-> save($y_log_obj);
                }else{
                    return apiResponse("201","未找到该有效年卡！");
                }
                $data['status'] = 2;

            }else if(!empty($data['c_m_id'])){
                //优惠券减免支付金额处理
                $coumem = new CouponMember();
                $where['c_m_id'] = $data['c_m_id'];
                $where['status'] = 0;
                $where['end_time'] = array('egt',date('YYY-mm-dd',time()));
                $coumeminfo = $coumem -> couponMemberInfo($where);
                if (empty($coumeminfo)) {
                    return apiResponse("201","优惠券已失效！");
                }else{
                    switch ($coumeminfo['type']) {
                        case '1':
                            // 定额
                            if ($coumeminfo['money'] > $device['price']) {
                                $data['pay_price'] = 0;
                            }
                            $data['pay_price'] = $device['price'] - $coumeminfo['money'];
                            break;
                        case '2':
                            // 折扣
                            $data['pay_price'] = $device['price']*$coumeminfo['money']/100;
                            break;
                        case '3':
                            // 满减
                            if ($coumeminfo['min_price'] <= $device['price']) {
                                $data['pay_price'] = $device['price'] - $coumeminfo['money'];
                            }else{
                                return apiResponse("201","当前选择优惠券未到满减条件！");
                            }
                            break;
                    }
                    $curcoupon['status'] = 1;
                    $coumem -> editCoupon($curcoupon,$where);
                }
            }

            if ( $data['pay_type'] == 4 ) {
                //余额支付处理
                $user = Db::name('user') -> where('u_id',$data['u_id']) -> find();
                if ($user['wallet'] >= $data['pay_price'] && $data['pay_price'] != 0) {
                    $user['wallet'] = $user['wallet'] - $data['pay_price'];
                    Db::name('user')->update($user);
                }else{
                    return apiResponse("201","余额不足！");
                }
                $data['status'] = 2;
            }

            $data['c_id'] = $device['c_id'];
            $data['total_price'] = $device['price'];
            $data['ctime'] = time();
            $data['discounts_price'] = $device['price'];
            $orderNo = $this->model->createOrder($data);
            Db::commit();
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            return apiResponse("201","发生未知错误！");
        }
        if ($orderNo) {
            if ($data['pay_type'] == 1) {
                $callback = 'http://' . $_SERVER['HTTP_HOST'] . '/api/order/checkUserOrder';
                $data = $this->wxPayBase($data['pay_price'], $orderNo['u_id'], $orderNo['ordernumber'], $callback);
                // $data = $this->wxPayBase(1, $orderNo['u_id'], $orderNo['ordernumber'], $callback);
                header('Content-Type:application/json; charset=utf-8');
                return $data;
            }else{
                return apiResponse("200","订单处理成功",$orderNo);
            }
        } else {
            return apiResponse(201, '下单失败', '');
        }
    }

    /**
     * @param Request $request
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author zhenHong~
     * 调起微信支付   正式用这个金钱 intval($order['pay_price']*100)
     */
    public function saveUserOrderInfo(Request $request)
    {
        $post = $request->post();
        $check = $this->validate($post, 'Order.saveUserOrderInfo');
        if ($check !== true) {
            return apiResponse(201, $check, '');
        }

        //  判断是否选择了 上门取车
        if ($request->has('get_car') && $request->post('get_car') == '1') {
            $car = $this->validate($post, 'Getcarorder.addCarOrder');
            if ($car !== true) {
                return apiResponse(201, $car, '');
            }
        }

        $bool = $this->model->getByOrderNumberSaveInfo($post);

        if ($bool) {
            $order = OrderModel::where('ordernumber', $post['ordernumber'])->field('u_id,pay_price')->find();

            $callback = 'http://' . $_SERVER['HTTP_HOST'] . '/reserve/order/checkUserOrder';

            $data = $this->wxPayBase($order['pay_price'], $order['u_id'], $post['ordernumber'], $callback);
            // $data = $this->wxPayBase(1, $order['u_id'], $post['ordernumber'], $callback);

            header('Content-Type:application/json; charset=utf-8');

            return $data;
        } else {
            return apiResponse(201, '订单更新失败', '');
        }
    }


    /**
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author zhenHong~
     * 获取当前用户保养订单
     */
    public function selectUserOrder()
    {
        $where = array_filter([
            'status' => input('status') ?: ['neq', 9],
            'u_id' => input('u_id')
        ], function ($data) {
            if ($data) {
                return true;
            } else {
                return false;
            }
        });
        $page = input('pagenum') ?: 1;
        $listnum = input('listnum') ?: 1;
        $result = $this->orders->getByUserIdSelectOrder($where, $page,$listnum);
        return apiResponse(200, '查询成功', $result);
    }


    /**
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author zhenHong~
     * 支付未付款订单  正式用 intval($order['pay_price']*100)
     * 业务逻辑：
     *      1、若存在order_id,则说明用户下单包含：上门取车订单 与 保养订单
     *      2、若接到 ordernumber 说明只是：预约上门 或 预约保养的订单
     */
    public function getByOrderNumberPay()
    {
        if (Request::instance()->has('order_id')) {
            $orderNo = OrderModel::where('id', input('order_id'))->value('ordernumber');
        } else {
            $orderNo = Request::instance()->post('ordernumber');
        }

        $order = OrderModel::where('ordernumber', $orderNo)->field('pay_price,u_id')->find();

        //  微信回调地址
        $callback = 'http://' . $_SERVER['HTTP_HOST'] . '/api/order/checkUserOrder';

        //  调起微信支付
        // $data = $this->wxPayBase(1, $order['u_id'], $orderNo, $callback);
        $data = $this->wxPayBase($order['pay_price'], $order['u_id'], $orderNo, $callback);

        header('Content-Type:application/json; charset=utf-8');

        return $data;
    }

    /**
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author zhenhong~
     * 查询订单详情
     */
    public function detailsUserOrder()
    {
        $orderNo['ordernumber'] = Request::instance()->post('ordernumber');

        $result = $this->orders->where($orderNo)->find();

        return apiResponse(200, '查询成功', $result);
    }


    /**
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author zhenHong~
     * 订单列表 平台与商户公用
     */
    public function selectOrderList()
    {
        $where = array_filter([
            'status' => input('status') ?: ['neq',9],
            'ordernumber|contactnum|phone|nickName' => input('keyword') ? ['like', '%'.input('keyword') . '%'] : '',
            'pay_type' => input('pay_type') ? input('pay_type') : ['in', '1,2,3,4'],
            'ctime' => getSelectTime(input('start'), input('end')),
            'c_id' => input('c_id') ?: '',
            'd_id' => input('d_id') ?: ''
        ], function ($data) {
            if ($data) {
                return true;
            } else {
                return false;
            }
        });
        $page = input('pagenum') ?: 1;
        $listNum = input('listNum') ?: 1;

        $result = $this->orders->selectOrder($where, $page,$listNum);
        return apiResponse(200, '查询成功', $result);
    }

    /**
     * @param Request $request
     * @return mixed
     * @author zhenhong~
     * 商户更改订单状态
     */
    public function updateUserOrderStatus(Request $request)
    {
        $post = $request->post();
        $num = $this->model->setStatusByOrderId($post['id'], $post['status']);
        if ($num) {
            return apiResponse(200, '更改订单状态成功', '');
        } else {
            return apiResponse(201, '更改失败', '');
        }
    }

    /**
     * @param $price
     * @param $uID
     * @param $orderNo
     * @param $callback
     * @return mixed
     * @author zhenhong~
     * 调起微信支付
     */
    public function wxPayBase($price, $uID, $orderNo, $callback)
    {
        //  判断用户id是否存在
        if (empty($uID)) {
            return apiResponse('201', '参数错误', "");
        }
        //  获取用户的openid
        $openid = Db::name("user")->where(['u_id' => $uID])->value('openid');

        //  调起微信统一下单支付接口
        $input = new \WxPayUnifiedOrder();
        $tools = new \JsApiPay();
        $input->SetOpenid($openid);
        $input->SetBody("速西智能洗车");
        $input->SetAttach("速西智能洗车");
        $input->SetGoods_tag("速西智能洗车");
        $input->SetOut_trade_no($orderNo);
        $input->SetTotal_fee(intval($price*100));
        $input->SetTime_start(date("YmdHis"));
        $input->SetTime_expire(date("YmdHis", time() + 600));
        $input->SetNotify_url($callback);
        $input->SetTrade_type("JSAPI");
        $order = \WxPayApi::unifiedOrder($input, 6);

        //  根据微信返回的通信标识 return_code 判断是否能唤起了支付
        if ($order['return_code'] == "FAIL") {
            return apiResponse(201, "未知错误，请联系管理员！", $price*100);
        }
        //  根据微信提供的交易标识符 result_code 来判断交易是否成功
        if (isset($order['result_code']) && $order['result_code'] == 'FAIL') {
            return apiResponse(201, $order['err_code_des'] ? $order['err_code_des'] : '订单信息错误', "");
        }
        $jsApiParameters = $tools->GetJsApiParameters($order);
        $jsApiParameters = stripslashes($jsApiParameters);

        //  根据当前订单编号缓存prepay_id
        Cache::set('prepay_id' . $orderNo, $order['prepay_id'], 600);

        return apiResponse(200, "支付签名成功", $jsApiParameters);
    }

    /**
     * @param $xml
     * @return mixed
     * xml 转array
     */
    public function xmlToArray($xml)
    {
        //将XML转为array
        $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $array_data;
    }


    /**
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     * @author zhenHong~
     * 微信支付回调url
     * 参数1：自己的订单号
     * 参数2：用户的openID
     * 参数3：微信的订单号
     */
    public function checkUserOrder()
    {
        $xml = $GLOBALS['HTTP_RAW_POST_DATA'];
        $xml_res = $this->xmlToArray($xml);
        if ($xml_res['return_code'] == 'SUCCESS') {
            $res = $this->model->saveOrderStatusAddUserBill($xml_res["out_trade_no"], $xml_res['openid'], $xml_res['transaction_id']);
            if ($res) {
                $xml = <<<xml
                    <xml>
                      <return_code><![CDATA[SUCCESS]]></return_code>
                      <return_msg><![CDATA[OK]]></return_msg>
                    </xml>
xml;
                echo $xml;
            }
        }
    }

    /**
     * @param Request $request
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author zhenhong~
     * 用户退款
     */
    public function handleBackMoney(Request $request)
    {
        $post = $request->post();

        $check = $this->validate($post, 'Order.handleBackMoney');

        if ($check !== true) {
            return apiResponse(201, $check, '');
        }

        $result = $this->model->checkOrderInfoByOrderID($post['order_id']);

        // 正式使用 $result['total_fee'], $result['refund_fee']
        $data = $this->returnMoneyToUser($result['out_trade_no'], $result['out_refund_no'], 1, 1);

        header('Content-Type:application/json; charset=utf-8');

        return $data;

    }


    /**
     * @param $tradeNo
     * @param $refundNo
     * @param $totalFee
     * @param $refundFee
     * @return mixed
     * @author zhenhong~
     * 调起微信退款接口
     * 提交退款申请后，退款有一定延时，用零钱支付的退款20分钟内到账，银行卡支付的退款3个工作日后重新查询退款状态。
     */
    public function returnMoneyToUser($tradeNo, $refundNo, $totalFee, $refundFee)
    {
        //  微信退款类
        $refund = new \WxPayRefund();
        $refund->SetOut_trade_no($tradeNo);
        $refund->SetOut_refund_no($refundNo);
        $refund->SetTotal_fee($totalFee);
        $refund->SetRefund_fee($refundFee);
        $refund->SetOp_user_id(\WxPayConfig::MCHID);
        $back = \WxPayApi::refund($refund, 6);

        //  返回结果
        if($back['return_code'] == 'FAIL' ){
            return apiResponse(201,'未知错误,请联系管理员','');
        }

        //  return_code SUCCESS时返回
        if(isset($back['result_code']) && $back['result_code'] == 'FAIL'){
            return apiResponse(201,'提交微信退款失败','');
        }

        return apiResponse(200,'申请成功,钱将在3个工作日内返到您的账户',$back);
    }


    /**
     * @return mixed
     * @throws \think\exception\PDOException
     * @author zhenhong~
     * 查询退款接口
     */
    public function queryOrderBackStatus(){
        $post = Request::instance()->post();
        $orderQuery = new \WxPayRefundQuery();
        $orderQuery->SetOut_trade_no($post['out_trade_no']);
        $orderQuery->SetOut_refund_no($post['out_refund_no']);
        $orderQuery->SetRefund_id($post['refund_id']);
        $orderQuery->SetTransaction_id($post['transaction_id']);
        $query = \WxPayApi::refundQuery($orderQuery, 6);

        if($query['return_code'] == 'FAIL'){
            return apiResponse(201,'退款查询错误','');
        }

        if(isset($query['result_code']) && $query['result_code'] == 'FAIL'){
            return apiResponse(201,'查询失败','');
        }

        if($query['result_code'] == 'SUCCESS' && $query['return_code'] == 'SUCCESS'){
            $result = $this->model->checkBackOrderInfo($post['out_trade_no'],$post['out_refund_no']);
            if($result){
                return apiResponse(200,'退款成功','');
            }else{
                return apiResponse(201,'查询失败','');
            }
        }else{
            return apiResponse(201,'查询失败','');
        }
    }

/**
 * [computeOrder description]
 * @author topqiang
 * @DateTime 2018-11-14T21:54:56+0800
 * @param    [type]                   $deviceId [description]
 * @param    [type]                   $data     [description]
 * @return   [type]                             [description]
 */
    public function computeOrder($deviceId,$data)
    {   

        $order = new OrderModel();
        $orders = new Orders();
        $device = new Device();
        if ( $data['status'] == 'finish' ) {
            $where['device_id'] = $deviceId;
            $where['status'] = 3;
            $res = $orders->where($where)->order('utime desc')->find();
            
            if (!empty( $res )) {
              $order->isUpdate() ->save( ['status'=>4,'id'=>$res['id']] );
            }else{
              echo "无需要修改的订单!";
            }
            
        }else{
            $deviceData['device_status'] = 1;
            if ($data['status'] == 'busy') {
                $deviceData['device_status'] = 2;
            }else if ($data['faultInfo'] == 'fault') {
                $deviceData['device_status'] = 4;
            }
            $deviceWhere['device_id'] = $deviceId;
            // $device->where($deviceWhere)->isUpdate()->save($deviceData);
            $device-> updateDevice($deviceData,$deviceWhere);
        }

        file_put_contents($deviceId.".txt",json_encode($data));
    }

/**
 * [updOrder description]
 * @author topqiang
 * @DateTime 2018-11-14T22:05:30+0800
 * @param    Request                  $request [description]
 * @return   [type]                            [description]
 */
    public function updOrder( Request $request )
    {   
        $order = new OrderModel();
        $orders = new Orders();
        $param = $request->post();
        file_put_contents( "orderparam.txt",json_encode($param));
        if ( $param['status'] == 'finish' ) {
            $where['device_id'] = $param['device_id'];
            $where['status'] = 3;
            $res = $orders->where($where)->order('utime desc')->find();
            if (empty($res)) {
                return apiResponse('201','暂无服务中的订单');
            }
            file_put_contents( $where['device_id']."order.txt",json_encode($res));

            $res1 = $order -> isUpdate() ->save( ['status'=>4,'id'=>$res['id']] );
            if ( !empty($res1) ) {
                return apiResponse("200","订单修改完成！");
            }else{
                return apiResponse("201","订单修改失败！");
            }
        }else{
            return apiResponse('201','订单状态未完成！');
        }
    }

    /**
     * [updOrderAndDevice description]
     * @author topqiang
     * @DateTime 2019-01-20T17:00:39+0800
     * @return   [type]                   [description]
     */
    public function updOrderAndDevice()
    {
      $orderwhere = [
        "status" => 3,
        "utime" => ['elt',time()-330]
      ];
      $order = new OrderModel();
      $res = $order -> where($orderwhere) -> update(['status'=>4,'utime'=>time()]);
      file_put_contents('updOrderAndDevice.txt',$order->getLastSql()."\n",FILE_APPEND);
      $deviceWhere = [
        'last_use_time' => ['elt',time()-330],
        'device_status' => 2
      ];
      $device = new Device();
      $res1 = $device -> where($deviceWhere) -> update(['device_status'=>1,'update_time'=>time()]);
      file_put_contents('updOrderAndDevice.txt',$device->getLastSql()."\n",FILE_APPEND);
      if (!empty($res) && !empty($res1)) {
        return "订单和设备修改成功！";
      }else{
        return "订单和设备修改失败！";
      }
    }
}